﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Xml;
using DirectUI.Mobile.UI.Controls;
using FrameWork.Classes;
using FrameWork.Classes.Data;
using FrameWork.Event;
using FrameWork.InterFace;
using FrameWork.Properties;
using ControlEventArgs = System.Windows.Forms.ControlEventArgs;

namespace FrameWork.Controls
{
    public class DirectUIComboBox : DirectUIPanel
    {
        private ScrollPanel spList;
        private int scrollBarWidth = 20;
        public DirectUIComboBox()
        {
           
            spList = new ScrollPanel();
            spList.ScrollBarWidth = scrollBarWidth;
            spList.ScrollBarButtonColor = Color.Gray;
            spList.ScrollReverse = true;
            spList.AlwaysShowScrollBar = true;
            spList.MovintSpeed =5;     
            spList.Controls.ControlAdded += new EventHandler<Event.ControlEventArgs>(Controls_ControlAdded);
     
            this.Controls.Add(spList);
            this.Height = 20;
            originBounds = this.Bounds;
            this.BackColor = Color.White;
            this.Name = Guid.NewGuid().ToString();
            this.BorderColor = Color.Black;
        }
        public Color BorderColor { get; set; }
        //public override void Invalidate()
        //{
        //    base.Invalidate();
        //    spList.Invalidate();
        //}
        void Controls_ControlAdded(object sender, Event.ControlEventArgs e)
        {
            if (!Expand)
            {
                originBounds = this.Bounds;
            }
                if (Items.Count > 1)
                {
                    e.Control.Bounds = new Rectangle(0, Items[Items.Count - 2].Top + Items[Items.Count - 2].Height, Items[Items.Count - 2].Width, Items[Items.Count - 2].Height);
                }
                else
                {
                    e.Control.Bounds = new Rectangle(0, 0, originBounds.Width-scrollBarWidth, originBounds.Height);
                    this.SelectedItemIndex = 0;
                }
                e.Control.Click += new EventHandler(Control_Click);
                spList.TopOffset = 0;
        
        }

        void Control_Click(object sender, EventArgs e)
        {
            if (this.SelectedItemIndex != Items.IndexOf((DirectUIControl)sender))
            {
                ((DirectUIControl)this.SelectedItem).BackColor = this.BackColor;
                this.SelectedItemIndex = Items.IndexOf((DirectUIControl)sender);
                ((DirectUIControl)sender).BackColor = this.SelectedItemBackColor;
            //    OnSelectedIndexChanged(null);
            }
            if (Expand)
            {
                Expand = false;
                int exHeight = this.Height;
                this.Height = originBounds.Height;
                spList.Visible = false;
                this.Invalidate(new Rectangle(0, 0, this.Width, exHeight));
            }
        }

        public override void OnKeyDown(KeyEventArgs e)
        {

         
            if (!e.Handled)
            {
                switch (e.KeyCode)
                {
                    case Keys.Down:
                        e.Handled = true;
                        ((DirectUIComboBoxItem)this.SelectedItem).BackColor = this.BackColor;
                        this.SelectedItemIndex++;
                        ((DirectUIComboBoxItem)this.SelectedItem).BackColor = this.SelectedItemBackColor;
                        
                        if(( ((DirectUIComboBoxItem)this.SelectedItem).Top+originBounds.Height)-spList.Height-spList.TopOffset>10){
                            spList.TopOffset += originBounds.Height;
                        }
                        this.Refresh();
                        break;

                    case Keys.Up:
                        e.Handled = true;
                        ((DirectUIComboBoxItem)this.SelectedItem).BackColor = this.BackColor;
                        this.SelectedItemIndex--;
                        ((DirectUIComboBoxItem)this.SelectedItem).BackColor = this.SelectedItemBackColor;
                        if ( ((DirectUIComboBoxItem)this.SelectedItem).Top < spList.TopOffset-10)
                        {
                            spList.TopOffset -= originBounds.Height;
                        }
                        this.Refresh();
                        break;
                    case (Keys.RButton | Keys.MButton | Keys.F17):
                        Expand = false;
                        this.Height = originBounds.Height;
                        spList.Visible = false;
                        this.Refresh();
                        break;
                    //default:
                    //    base.OnKeyDown(e);
                    //    //  ScrollBarVisible = false;
                    //    break;
                }
            }
        }

        public override bool Active { get { return true; } }

        public bool Expand { get; set; }
      //  public ObjectCollection Items { get; set; }
        private object itemSource;
        public object ItemSource
        {
            get
            {
                return itemSource;
            }
            set
            {
                itemSource = value;
                if (value is IList)
                {
                    BindTolist((IList)value);
                }
                else if (value is System.ComponentModel.IListSource)
                {
                    BindTolist(((System.ComponentModel.IListSource)value).GetList());
                }
                else if (value is XmlNodeList)
                {
                    BindToXmlNodeList((XmlNodeList)value);
                }
                else
                {
                    throw new NotSupportedException("DataSource Must Implment Interface  'System.ComponentModel.IListSource' or 'Sysem.Collection.IList'");
                }
                SelectedItemIndex = 0;
            }
        }
        protected void BindToXmlNodeList(XmlNodeList dataSource)
        {
            foreach (XmlNode node in dataSource)
            {
                if (string.IsNullOrEmpty(DataTextField) || string.IsNullOrEmpty(DataValueField))
                {
                    throw new Exception.DataBinderException("ComboBox's 'DataTextField' and 'DataValueField' property need to be set for data bind");
                }
                DirectUIComboBoxItem item = new DirectUIComboBoxItem();
                XmlNode textNode = node.SelectSingleNode(DataTextField);
                XmlNode valueNode = node.SelectSingleNode(DataValueField);
                if (textNode == null || valueNode == null)
                {
                    continue;
                }
                item.Text = textNode.InnerText;
                item.Value = valueNode.InnerText;
                spList.Controls.Add(item);
            }
            SelectedItemIndex = 0;
            this.Refresh();
        }
        public DirectUIControlCollection Items
        {
            get
            {
                return spList.Controls;
            }
            //set
            //{
                //if (value is IList)
                //{
                //    BindTolist((IList)value);
                //}
                //else if (value is System.ComponentModel.IListSource)
                //{
                //    BindTolist(((System.ComponentModel.IListSource)value).GetList());
                //}
                //else
                //{
                //    throw new NotSupportedException("DataSource Must Implment Interface  'System.ComponentModel.IListSource' or 'Sysem.Collection.IList'");
                //}
                //SelectedItemIndex = 0;
            //}
        }
        // private Object selectedItem;
        private int selectedItemIndex;
        private Rectangle originBounds;
      
        public Object SelectedItem
        {
            get
            {
                if (SelectedItemIndex >= Items.Count || SelectedItemIndex < 0)
                {
                  //  SelectedItemIndex = 0;
                    return null;
                }
                return Items[SelectedItemIndex];
            }
          
        }
        public int SelectedItemIndex
        {
            get
            {
                return selectedItemIndex;
            }
            set
            {
                if (selectedItemIndex == value&&selectedItemIndex!=0)
                {
                    return;
                }
                if (value >= Items.Count)
                {
                    selectedItemIndex = Items.Count - 1;
                    //throw new IndexOutOfRangeException();
                }
                else if (value < 0)
                {
                    selectedItemIndex = 0;
                }
                else
                {
                    selectedItemIndex = value;
                }
                OnSelectedIndexChanged(new EventArgs());
                OnPropertyChanged(new PropertyChangingEventArgs("SelectedItemIndex"));
             OnPropertyChanged(new PropertyChangingEventArgs("SelectedValue"));
             OnPropertyChanged(new PropertyChangingEventArgs("SelectedText"));
            }
        }
        public event EventHandler SelectedIndexChanged;
        public virtual void OnSelectedIndexChanged(EventArgs e)
        {
            if (SelectedIndexChanged != null)
            {
                SelectedIndexChanged(this, e);
            }
        }
        public class ObjectCollection
        {
            public event EventHandler ItemChanged;
            public void OnItemChanged(EventArgs e)
            {
                if (ItemChanged != null)
                {
                    ItemChanged(this, e);
                }
            }
            private IList<object> _items;
            public void Add(object item)
            {
                if (_items == null)
                {
                    _items = new List<object>();
                }
                if (item.GetType() != typeof(DirectUIComboBoxItem))
                {
                    throw new System.Exception("Only Support ComboxBoxItem Type");
                }
                _items.Add(item);
                OnItemChanged(null);

            }
            public void Clear()
            {
                if (_items != null)
                {
                    _items.Clear();
                }
                OnItemChanged(null);
            }
            public object this[int index]
            {
                get
                {
                    return _items[index];
                }
            }
            public int Count
            {
                get
                {
                    if (_items == null)
                    {
                        return 0;
                    }
                    return _items.Count;
                }
            }

        }
        private Color selectedItemBackColor = Color.Gray;
        public Color SelectedItemBackColor
        {
            get
            {
                return selectedItemBackColor;
            }
            set
            {
                selectedItemBackColor = value;
            }
        }
        public override void OnLostFocus()
        {
            base.OnLostFocus();
            Expand = false;
            this.Height = originBounds.Height;
            spList.Visible = false;
            this.Refresh();
        }
        public override void Invalidate(Rectangle bounds)
        {
            if (!Visible) return;
            if (Initializing) return;
            if (Container == null) return;

            bounds.Offset(Left, Top);
            // don't let the child control invalidate anything outside the own bounds:
       //     ClipRectangle(ref bounds);
            if (Container != null)
            {
                Container.Invalidate(bounds);
            }
            else
            {
                Host.Invalidate(bounds);
            }
        }
        public override bool OnClick(PointEventArgs e)
        {
            if (Expand)
            {
                int index = e.Y / originBounds.Height - 1;
                if (index >= 0)
                {
                    base.OnClick(e);
                    return false;
                }
                else
                {
                    Expand = false;
                    int exHeight = this.Height;
                    this.Height = originBounds.Height;
                    spList.Visible = false;
                    this.Invalidate(new Rectangle(0, 0, this.Width, exHeight));
                }
                return false;
            }else{
                base.OnClick(e);
                spList.ResetDisplayHeight();
           //     spList.Refresh();
                Expand = true;
                originBounds = this.Bounds;          
                if (this.Items.Count < 5)
                {
                    this.Height = this.Height + this.Items.Count * this.Height;
                    spList.AlwaysShowScrollBar = false;        
                }
                else
                {
                    spList.AlwaysShowScrollBar = true;             
                    this.Height = this.Height +5 * this.Height;
                }
                spList.Bounds = new Rectangle(0, originBounds.Height, originBounds.Width-1, this.Height - originBounds.Height-1);
      spList.Visible = true;          
                if (this.Parent != null)
                {
                    DirectUIControlCollection fc = (DirectUIControlCollection)((IMultiControlContainer)this.Parent).Controls;
                    fc.Remove(this);
                    fc.Insert(0, this);
                }
            }
            Invalidate();
            return false;
        }
        public override void OnPaint(DirectUIPaintEventArgs e)
        {        
            if (Items == null )
            {
                EndPaint();
                return;
            }
            if (Items.Count == 0)
            {
                EndPaint();
                return;
            }
            if (((DirectUIComboBoxItem)this.SelectedItem).BackColor != this.SelectedItemBackColor)
            {
                ((DirectUIComboBoxItem)this.SelectedItem).BackColor = this.SelectedItemBackColor;
            }
            base.OnPaint(e);
            e.Graphics.DrawString(((DirectUIComboBoxItem)SelectedItem).Text, this.Font, new SolidBrush(this.ForeColor), e.ControlBounds.Left, e.ControlBounds.Top);
            if (Expand)
            {
                if (this.BorderColor != Color.Transparent && this.BorderColor != Color.Empty)
                {
                    e.Graphics.DrawRectangle(new Pen(BorderColor), new Rectangle(e.ControlBounds.Left, e.ControlBounds.Top, originBounds.Width, originBounds.Height - 1));
                }
                     e.Graphics.DrawRectangle(new Pen(Color.Black), new Rectangle(e.ControlBounds.Left, e.ControlBounds.Top+originBounds.Height,e.ControlBounds.Width-1, e.ControlBounds.Height-originBounds.Height-1));

                e.Graphics.DrawImage(Resource.combobox_arrow_up, new Rectangle(e.ControlBounds.Left + this.Width - 20, e.ControlBounds.Top, 20, 20), new Rectangle(0, 0, 20, 20), GraphicsUnit.Pixel);
            }
            else
            {
                if (this.BorderColor != Color.Transparent && this.BorderColor != Color.Empty)
                {
                    e.Graphics.DrawRectangle(new Pen(BorderColor), new Rectangle(e.ControlBounds.Left, e.ControlBounds.Top, this.Bounds.Width, this.Bounds.Height));
                }
                  e.Graphics.DrawImage(Resource.combobox_arrow_down, new Rectangle(e.ControlBounds.Left + this.Width - 20, e.ControlBounds.Top, 20, 20), new Rectangle(0, 0, 20, 20), GraphicsUnit.Pixel);

            }
     

        }
        public string DataTextField { get; set; }
        public string DataValueField { get; set; }
        private void BindItems(DataBinding binding)
        {
            binding.Mode = BindingMode.OneWay;
            DataSourceProvider dataSource = (DataSourceProvider)binding.DataSource;

            object list = null;
            if (binding.Path == null)
            {
                list = dataSource.Data;
            }
            else
            {
                list = DataBinder.GetPropertyValue(dataSource.Data, binding.Path.Path);
            }
            if (list is IList)
            {
                BindTolist((IList)list);
            }
            else if (list is System.ComponentModel.IListSource)
            {
                BindTolist(((System.ComponentModel.IListSource)list).GetList());
            }
            else
            {
                throw new NotSupportedException("DataSource Must Implment Interface  'System.ComponentModel.IListSource' or 'Sysem.Collection.IList'");
            }
          
        }
  
        public string SelectedText
        {
            get
            {
                if (SelectedItem != null)
                {
                    return ((DirectUIComboBoxItem)SelectedItem).Text;
                }
                return "";
            }
            set
            {
                for (int i = 0; i < Items.Count; i++)
                {
                    if (((DirectUIComboBoxItem)Items[i]).Text == value)
                    {
                        SelectedItemIndex = i;
                        break;
                    }
                }
            }
        }
        public string SelectedValue
        {
            get
            {
                if (SelectedItem != null)
                {
                    return ((DirectUIComboBoxItem)SelectedItem).Value;
                }
                return "";
            }
            set
            {
                for (int i = 0; i < Items.Count; i++)
                {
                    if (((DirectUIComboBoxItem)Items[i]).Value == value)
                    {
                        SelectedItemIndex = i;
                        break;
                    }
                }
            }
        }
        protected void BindTolist(IList dataSource)
        {
            foreach (object o in dataSource)
            {
                if (o is DirectUIComboBoxItem)
                {
                    this.Items.Add((DirectUIControl)o);
                }
                else
                {
                    if (string.IsNullOrEmpty(DataTextField) || string.IsNullOrEmpty(DataValueField))
                    {
                        throw new Exception.DataBinderException("ComboBox's 'DataTextField' and 'DataValueField' property need to be set for data bind");
                    }
                    DirectUIComboBoxItem item = new DirectUIComboBoxItem();
                    item.Text = (string)DataBinder.GetPropertyValue(o, DataTextField);
                    item.Value =(string)DataBinder.GetPropertyValue(o, DataValueField);
                    this.Items.Add(item);
                }
            }
            SelectedItemIndex = 0;
            this.Refresh();
        }
        public override void Refresh()
        {
            if (spList != null)
            {
                spList.ResetDisplayHeight();
            }
            base.Refresh();
        }
    }
}
